package ca.psquared.superbrixgame.scheduler;

import com.google.common.collect.Lists;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.SlickException;

import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;

public class Scheduler {

    private List<ITask> tasks = Lists.newArrayList();
    private List<ITask> queuedTasks = Lists.newArrayList();
    private List<ITask> tasksToRemove = Lists.newArrayList();
    private Queue<ITask> queuedExclusiveTasks = new ArrayDeque<ITask>();

    public Scheduler() {
    }

    public void update(GameContainer gameContainer, int delta) throws SlickException {

        // Create variable from peek()
        // if variable != null... execute
        //    if isDone() remove()
        // else, do regular tasks

        final ITask currentExclusiveTask = queuedExclusiveTasks.peek();

        if (currentExclusiveTask != null) {
            currentExclusiveTask.execute(gameContainer, delta);
            if (currentExclusiveTask.isDone()) {
                queuedExclusiveTasks.remove();
            }

        } else {

            final Iterator<ITask> taskIterator = tasks.iterator();

            // Running tasks
            while (taskIterator.hasNext()) {
                final ITask task = taskIterator.next();
                task.execute(gameContainer, delta);

                // Remove task if finished
                if (task.isDone()) {
                    taskIterator.remove();
                }
            }

            // Tasks to be removed
            tasks.removeAll(tasksToRemove);
            queuedTasks.removeAll(tasksToRemove);
            tasksToRemove.clear();

            // Tasks to be added
            tasks.addAll(queuedTasks);
            queuedTasks.clear();
        }

    }

    public ITaskHandle addTask(final ITask task) {
        queuedTasks.add(task);

        return new ITaskHandle() {
            @Override
            public void remove() {
                tasksToRemove.add(task);
            }
        };
    }

    public ITaskHandle addExclusiveTask(final ITask task) {
        queuedExclusiveTasks.add(task);

        return new ITaskHandle() {
            @Override
            public void remove() {
                queuedExclusiveTasks.remove(task);
            }
        };
    }
}